import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import * as readline from 'readline';

export function activate(context: vscode.ExtensionContext) {
	const provider = new CssVariableListView(context);
	context.subscriptions.push(
		vscode.window.registerWebviewViewProvider(
			CssVariableListView.viewType,
			provider
		)
	);
	provider.recoverState();
}

class CssVariableListView implements vscode.WebviewViewProvider {
	public static readonly viewType = 'Variable.VariableList';

	private _view?: vscode.WebviewView;

	constructor(private readonly _context: vscode.ExtensionContext) { }

	public async resolveWebviewView(webviewView: vscode.WebviewView, context: vscode.WebviewViewResolveContext<unknown>, token: vscode.CancellationToken): Promise<void> {
		this._view = webviewView;

		webviewView.webview.options = {
			enableScripts: true,
			localResourceRoots: [this._context.extensionUri]
		};

		webviewView.webview.html = await this._getHtmlForWebview(webviewView.webview);

		webviewView.webview.onDidReceiveMessage(async message => {
			const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
			switch (message.command) {
				case 'readAndEvaluateFile':
					if (!workspaceFolder) {
						webviewView.webview.postMessage({ command: 'errorMessage', errorMessage: 'No active workspace folder.' });
						return;
					}
					const absoluteFilePath = path.join(workspaceFolder.uri.fsPath, message.filePath);
					try {
						const variables = await this.readAndExtractVariables(absoluteFilePath);
						webviewView.webview.postMessage({ command: 'fileContent', content: variables });
						this.saveLastFilePath(workspaceFolder.uri.fsPath, message.filePath);
          } catch (error: any) {
            console.error(error);
            webviewView.webview.postMessage({ command: 'errorMessage', errorMessage: `Failed to read or evaluate file: ${error.message}` });
          }
					break;
				case 'showNotification':
					vscode.window.showInformationMessage(message.message);
					break;
				case 'getLastFilePath':
					if (workspaceFolder) {
						const lastFilePath = this.getLastFilePath(workspaceFolder.uri.fsPath);
						webviewView.webview.postMessage({ command: 'setLastFilePath', filePath: lastFilePath });
					}
					break;
				default:
					break;
			}
		}, undefined, this._context.subscriptions);

		webviewView.onDidDispose(() => {
			this._view = undefined;
		});
		this._view.webview.postMessage({ command: 'getLastFilePath' });
	}

	private saveLastFilePath(workspacePath: string, filePath: string): void {
		const key = `lastFilePath_${encodeURIComponent(workspacePath)}`;
		this._context.workspaceState.update(key, filePath);
	}

	private getLastFilePath(workspacePath: string): string | undefined {
		const key = `lastFilePath_${encodeURIComponent(workspacePath)}`;
		return this._context.workspaceState.get(key);
	}

	public recoverState() {
		const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
		if (workspaceFolder) {
			const lastFilePath = this.getLastFilePath(workspaceFolder.uri.fsPath);
			this._view?.webview.postMessage({ command: 'setLastFilePath', filePath: lastFilePath });
		}
	}

	private async readAndExtractVariables(filePath: string): Promise<{ name: string, color: string }[]> {
		const variables: { name: string, color: string }[] = [];
		const fileStream = fs.createReadStream(filePath);
		const rl = readline.createInterface({
			input: fileStream,
			crlfDelay: Infinity
		});

		const nameReg = /(--\w+(?:-\w+)*)/;
		const colorReg = /:\s*([^;,]+)/; // Updated to stop at ',' or ';'

		for await (const line of rl) {
			const nameMatch = line.match(nameReg);
			const colorMatch = line.match(colorReg);
	
			if (nameMatch && colorMatch) {
				const name = nameMatch[1]; // This will include the '--' prefix
				const color = colorMatch[1].trim().replace(/['"]/g, '');
				variables.push({ name, color });
			}
		}

		return variables;
	}

  private async _getHtmlForWebview(webview: vscode.Webview): Promise<string> {
		const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._context.extensionUri,  'views', 'index.js'));

		const styleResetUri = webview.asWebviewUri(vscode.Uri.joinPath(this._context.extensionUri,  'views', 'reset.css'));
		const styleMainUri = webview.asWebviewUri(vscode.Uri.joinPath(this._context.extensionUri,  'views', 'main.css'));
		const filePathOnDisk = vscode.Uri.joinPath(
			this._context.extensionUri,
			 'views', 'index.html'
		);
		const nonce = getNonce();

		const indexBytes = await vscode.workspace.fs.readFile(filePathOnDisk);
		const indexData =( new TextDecoder('utf-8')).decode(indexBytes);

		const  htmlContent = indexData.replace('${styleResetUri}', styleResetUri.toString())
			.replace('${styleMainUri}', styleMainUri.toString())
			.replace('${scriptUri}', scriptUri.toString())
			.replace('${nonce}', nonce);

		return htmlContent;
	}
}

function getNonce() {
	let text = '';
	const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	for (let i = 0; i < 32; i++) {
		text += possible.charAt(Math.floor(Math.random() * possible.length));
	}
	return text;
}

export function deactivate() { }